﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.ComponentModel;
using GDI = System.Drawing;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Win32;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure;

namespace AzureBlob
{
    class SysTool
    {

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("User32.dll")]
        internal static extern IntPtr LoadIcon(IntPtr hInst, string filename);

        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        internal static extern IntPtr ExtractIcon(IntPtr hInst, string filename, int index);

        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        internal static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation,
            string lpFile, string lpParameters, string lpDirectory, int nShowCmd);

        static public string GetContentType(string ext)
        {
            var key = Registry.ClassesRoot.OpenSubKey(ext);
            if (key != null)
            {
                var result = key.GetValue("Content Type");
                if (result != null)
                    return result.ToString();
            }
            return null;
        }


        static Dictionary<string, ImageSource> iconTable = new Dictionary<string, ImageSource>();
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="extName">(.txt)</param>
        /// <returns></returns>
        static public ImageSource GetSystemIconByExt(string extName)
        {
            ImageSource image;
            if (iconTable.ContainsKey(extName))
                image = iconTable[extName];
            else
            {
                string fileType = GetFileType(extName);
                string iconString = GetDefaultIcon(fileType);
                int index = 0;
                int p = iconString.LastIndexOf(',');
                if (p != -1)
                {
                    if (!int.TryParse(iconString.Substring(p + 1), out index))
                        index = 0;
                    iconString = iconString.Substring(0, p);
                }
                if (iconString.Length > 0 && iconString[0] == '\"')
                    iconString = iconString.Substring(1);
                if (iconString.Length > 0 && iconString[iconString.Length - 1] == '\"')
                    iconString = iconString.Substring(0, iconString.Length - 1);
                IntPtr hIcon = ExtractIcon(GetModuleHandle(null), iconString, index);
                image = ImageSourceFrom(GDI.Icon.FromHandle(hIcon));
                iconTable.Add(extName, image);
            }
            return image;
        }
        
        private static string GetFileType(string extName)
        {
            var key = Registry.ClassesRoot.OpenSubKey(extName);
            if (key != null)
            {
                return (string)key.GetValue(string.Empty);
            }
            else
                return "Unknown";

        }
        
        private static string GetDefaultIcon(string fileType)
        {
            
            RegistryKey keyIcon = keyIcon = Registry.ClassesRoot.OpenSubKey(fileType + @"\DefaultIcon");
            string result = null;
            if (keyIcon != null)
            {
                result = (string)keyIcon.GetValue(string.Empty);
                if (result.IndexOf("%1") != -1) {
                    RegistryKey keyClsID = Registry.ClassesRoot.OpenSubKey(fileType + @"\CLSID");
                    if (keyClsID != null)
                    {
                        string clsid = (string)keyClsID.GetValue(string.Empty);
                        keyIcon = Registry.ClassesRoot.OpenSubKey(@"CLSID\" + clsid + @"\DefaultIcon");
                        result = (string)keyIcon.GetValue(string.Empty);
                    }
                    else
                        result = null;
                }
            }
            if (result != null)
                return result;
            else
                return @"%SystemRoot%\System32\shell32.dll,0";
        }

        

        

        internal static ImageSource ImageSourceFrom(GDI.Icon icon)
        {
            GDI.Bitmap bmp = icon.ToBitmap();

            MemoryStream strm = new MemoryStream();
            bmp.Save(strm, System.Drawing.Imaging.ImageFormat.Png);

            BitmapImage bmpImage = new BitmapImage();
            bmpImage.BeginInit();
            strm.Seek(0, SeekOrigin.Begin);
            bmpImage.StreamSource = strm;
            bmpImage.EndInit();

            return bmpImage;
        }


        [StructLayout(LayoutKind.Sequential)]
        public struct SHFILEINFO
        {
            public IntPtr hIcon;
            public int iIcon;
            public int dwAttributes;
            public string szDisplayName;
            public string szTypeName;
        }

        public enum IconSize
        {
            Large,
            Small
        }


        //private const uint SHGFI_SYSICONINDEX = 0x4000;
        //private const uint SHGFI_ICON = 0x100;
        //private const uint SHGFI_LARGEICON = 0x0;
        //private const uint SHGFI_SMALLICON = 0x1;

        //[DllImport("Shell32.dll")]
        //public static extern int SHGetFileInfo(string path, uint fileAttributes, out SHFILEINFO psfi, uint fileInfo, uint flags);

        //public static GDI.Icon GetIcon(string path, IconSize iconSize)
        //{
        //    SHFILEINFO info = new SHFILEINFO();
        //    uint size = iconSize == IconSize.Large ? SHGFI_LARGEICON : SHGFI_SMALLICON;
        //    uint flags = SHGFI_SYSICONINDEX | size | SHGFI_ICON;
        //    int hTcdf = SHGetFileInfo(path, 0, out info, (uint)Marshal.SizeOf(typeof(SHFILEINFO)), flags);
        //    IntPtr handleIcon = info.hIcon;
        //    GDI.Icon ico = GDI.Icon.FromHandle(handleIcon);
        //    return ico;
        //}


        public static AccountInfo[] GetAccountList()
        {
            RegistryKey rKey = Registry.CurrentUser.OpenSubKey(@"Software\CHOU\AzureBlob");
            if (rKey == null)
            {
                rKey = Registry.CurrentUser.CreateSubKey(@"Software\CHOU\AzureBlob");
                rKey.SetValue(string.Empty, 0, RegistryValueKind.DWord);
                rKey.Close();
                return new AccountInfo[0];
            }
            else
            {
                int count = (int)rKey.GetValue(string.Empty);
                List<AccountInfo> result = new List<AccountInfo>();
                for (int i = 0; i < count; i++)
                {
                    string name = (string)rKey.GetValue("Name" + i);
                    string key = (string)rKey.GetValue("Key" + i);
                    string cdn = (string)rKey.GetValue("CDN" + i);
                    if (name != null && key != null)
                    {
                        result.Add(new AccountInfo(name, key, cdn, false));
                    }
                }
                rKey.Close();
                return result.ToArray();
            }
        }

        internal static void AddAccount(string name, string key, string cdn)
        {
            RegistryKey rKey = Registry.CurrentUser.OpenSubKey(@"Software\CHOU\AzureBlob", true);
            int count = (int)rKey.GetValue(string.Empty);
            rKey.SetValue("Name" + count, name, RegistryValueKind.String);
            rKey.SetValue("Key" + count, key, RegistryValueKind.String);
            rKey.SetValue("CDN" + count, cdn, RegistryValueKind.String);
            rKey.SetValue(string.Empty, ++count, RegistryValueKind.DWord);
            rKey.Close();
        }

        internal static void ViewInBrowser(string url) {
            ShellExecute(IntPtr.Zero, "open", url, null, null, 1);
        }

        internal static void SetAccount(string name, string key, string cdn)
        {
            RegistryKey rKey = Registry.CurrentUser.OpenSubKey(@"Software\CHOU\AzureBlob", true);
            int count = (int)rKey.GetValue(string.Empty);
            for (int i = 0; i < count; i++)
            {
                if (name.Equals(rKey.GetValue("Name" + i)))
                {
                    rKey.SetValue("Key" + i, key, RegistryValueKind.String);
                    rKey.SetValue("CDN" + i, cdn, RegistryValueKind.String);
                    return;
                }
            }
            rKey.Close();
        }

        internal static void RemoveAccount(int index, AccountInfo accountInfo)
        {
            RegistryKey rKey = Registry.CurrentUser.OpenSubKey(@"Software\CHOU\AzureBlob", true);
            int count = (int)rKey.GetValue(string.Empty);
            for (int i = 0; i < count; i++)
            {
                if (i > index)
                {
                    string accountName = (string)rKey.GetValue("Name" + i, null);
                    string accountKey = (string)rKey.GetValue("Key" + i, null);
                    string cdn = (string)rKey.GetValue("CDN" + i, null);
                    if (accountName != null)
                        rKey.SetValue("Name" + (i - 1), accountName);
                    if (accountKey != null)
                        rKey.SetValue("Key" + (i - 1), accountKey);
                    if (cdn != null)
                        rKey.SetValue("CDN" + (i - 1), cdn);

                }
            }
            count--;
            rKey.SetValue(string.Empty, count);
            rKey.DeleteValue("Name" + count);
            rKey.DeleteValue("Key" + count);
            rKey.DeleteValue("CDN" + count);
        }
    }
}
